package com.dhcc.core.modules.system.controller;


import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.dhcc.core.config.properties.SysProperties;
import com.dhcc.core.framework.annotion.BussinessLog;
import com.dhcc.core.framework.base.controller.BaseController;
import com.dhcc.core.framework.constant.Const;
import com.dhcc.core.framework.exception.BizException;
import com.dhcc.core.framework.exception.BizExceptionEnum;
import com.dhcc.core.framework.result.R;
import com.dhcc.core.framework.result.node.ZTreeNode;
import com.dhcc.core.framework.result.page.PageFactory;
import com.dhcc.core.framework.security.ShiroKit;
import com.dhcc.core.framework.util.ArrayUtil;
import com.dhcc.core.framework.util.CommonUtil;
import com.dhcc.core.modules.system.entity.PanAttachment;
import com.dhcc.core.modules.system.entity.PanFile;
import com.dhcc.core.modules.system.entity.PanFolder;
import com.dhcc.core.modules.system.service.IPanAttachmentService;
import com.dhcc.core.modules.system.service.IPanFileService;
import com.dhcc.core.modules.system.service.IPanFolderService;
import com.dhcc.core.modules.system.warpper.PanFileWarpper;


/**
 * 个人文件
 * 
 * @ClassName: PanController
 * @Description: TODO
 * @author mk
 * @date 2018-08-30 20:44:24
 */
@Controller
@RequestMapping("${sys.backendPath}/pan")
public class PanController extends BaseController {

	private String PREFIX = "/backend/system/pan/";

	@Autowired
	private IPanFileService panFileService;

    @Autowired
    private IPanFolderService panFolderService;


    @Autowired
    private SysProperties sysProperties;

    @Autowired
    private IPanAttachmentService panAttachmentService;

    /**
     * 跳转到列表首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "index.html";
    }

    /**
     * 获取列表
     */
	@SuppressWarnings("unchecked")
    @RequestMapping(value = "/file/list")
    @ResponseBody
    public Object fileList(@RequestParam Map<String, Object> params,Long folderId) {
        params.put("userId",ShiroKit.getUser().getId());
        Page<PanAttachment> page = new PageFactory<PanAttachment>().defaultPage();
        String fileName = (String) params.get("fileName");
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");
        List<PanAttachment> result = this.panFileService.getUserAttachmentsOfFolder(page, folderId, this.getLoginUserId(), fileName, startDate, endDate);
        page.setRecords((List<PanAttachment>) new PanFileWarpper(result).warp());
        return R.packForBT(page);
    }


    /**
     * 删除
     */
    @RequestMapping(value = "/file/delete")
    @ResponseBody
    @BussinessLog(value = "删除")
    public Object delete(@RequestParam String fileIds) {
        Long[] panFileIds = ArrayUtil.stringformatToArray(fileIds, ArrayUtil.COMMA);
        this.panFileService.deleteFile(this.getLoginUserId(),panFileIds);
        return R.ok();
    }


    /**
     * 文件上传管理
     * @param file
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, path = "/file/upload")
    @ResponseBody
    public R fileupload(@RequestPart("file") MultipartFile file,@RequestParam Integer source,@RequestParam Long folderId, HttpServletRequest request) {
        PanFile panFile  = this.panFileService.fileUpload(file,source,folderId);
        return R.ok().put("file", panFile);
    }

    /**
     * 文本图片上传
     * @param file
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, path = "/file/uploadImg")
    @ResponseBody
    public JSONObject uploadImg(@RequestPart("imgFile") MultipartFile file) {
        PanFile panFile =  this.panFileService.fileUpload(file,1, Const.PAN_DEFAULT_FOLDER_ID);
        JSONObject obj =new JSONObject();
        try {
            obj.put("error",.0);
            obj.put("url", "/file/image/" + panFile.getAttachment().getFilePath());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * 个人文件ID 文件下载
     * @param fileIds
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, path = "/file/downbyfileid")
    @ResponseBody
    public void fileDownloadByFileId(HttpServletRequest request, HttpServletResponse response, @RequestParam String fileIds) {
        Long[]  panfileIds = ArrayUtil.stringToLongArray(fileIds,ArrayUtil.COMMA);
        List<PanAttachment> attachmentEntities = this.panFileService.getAttachmentsByFileIds(panfileIds);
        if(!attachmentEntities.isEmpty()){
            //响应头的设置
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            if(attachmentEntities.size() == 1){//只有1的时候不打包下载
                singleDownload(request,response,attachmentEntities.get(0));//单独下载
            }else {
                batchDownload(request,response,attachmentEntities);//批量下载
            }
        }
    }
    /**
     * 附件Id 文件下载
     * @param attachmentId
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, path = "/file/downbyattachmentid")
    @ResponseBody
    public void fileDownloadByAttachmentId(HttpServletRequest request, HttpServletResponse response, @RequestParam Long attachmentId) {
        PanAttachment attachmentEntities = this.panAttachmentService.selectById(attachmentId);
        if(attachmentEntities != null){
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            singleDownload(request,response,attachmentEntities);//单独下载
        }
    }
    /**
     *  单独下载
     * @param request
     * @param response
     * @param attachment
     */
    private void singleDownload(HttpServletRequest request, HttpServletResponse response,PanAttachment attachment){
        //解决不同浏览器压缩包名字含有中文时乱码的问题
        String downloadName = attachment.getOriginalName();
        String agent = request.getHeader("USER-AGENT");
        try {
            if (agent.contains("MSIE")||agent.contains("Trident")) {
                downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
            } else {
                downloadName = new String(downloadName.getBytes("UTF-8"),"ISO-8859-1");
            }
            InputStream inStream = new FileInputStream(sysProperties.getFileUploadPath() + attachment.getFilePath() );// 文件的存放路径
            response.addHeader("Content-Disposition", "attachment; filename=\"" + downloadName + "\"");
            // 循环取出流中的数据
            byte[] b = new byte[100];
            int len;
            while ((len = inStream.read(b)) > 0)
                response.getOutputStream().write(b, 0, len);
            inStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 批量下载
     * @param request
     * @param response
     * @param attachments
     */
    private void batchDownload(HttpServletRequest request, HttpServletResponse response,List<PanAttachment> attachments){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd");
        String downloadName =simpleDateFormat.format(new Date()) + ".zip";
        try {
            downloadName = new String(downloadName.getBytes("UTF-8"),"ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");
        //设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zipos = null;
        try {
            zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            zipos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法
        } catch (Exception e) {
            e.printStackTrace();
        }
        DataOutputStream os = null;
        for(int i = 0; i < attachments.size(); i++ ){
            PanAttachment attachment = attachments.get(i);
            File file = new File(sysProperties.getFileUploadPath() + attachment.getFilePath());
            try {
                //添加ZipEntry，并ZipEntry中写入文件流
                //这里，加上i是防止要下载的文件有重名的导致下载失败
                zipos.putNextEntry(new ZipEntry(i + attachment.getOriginalName()));
                os = new DataOutputStream(zipos);
                InputStream is = new FileInputStream(file);
                byte[] b = new byte[100];
                int length = 0;
                while((length = is.read(b))!= -1){
                    os.write(b, 0, length);
                }
                is.close();
                zipos.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            os.flush();
            os.close();
            zipos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文件夹的tree列表
     */
    @RequestMapping(value = "/folder/tree")
    @ResponseBody
    public List<ZTreeNode> folderTree() {
        return this.panFolderService.tree(ShiroKit.getUser().getId());
    }
    /**
     * 跳转到添加个人文件夹
     */
    @RequestMapping("/folder/to_add")
    public String folderAdd() {
        return PREFIX + "folder_add.html";
    }

    /**
     * 跳转到修改个人文件夹
     */
    @RequestMapping("/folder/to_update/{folderId}")
    public String folderUpdate(@PathVariable Long folderId, Model model) {
        PanFolder folder = this.panFolderService.selectById(folderId);
        model.addAttribute("folder",folder);
        return PREFIX + "folder_edit.html";
    }


    /**
     * 新增个人文件夹
     */
    @RequestMapping(value = "/folder/add")
    @ResponseBody
    @BussinessLog(value = "新增个人文件夹")
    public Object add(PanFolder folder) {
        if (CommonUtil.isOneEmpty(folder)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        folder.insert();
        return R.ok();
    }

    /**
     * 删除个人文件夹
     */
    @RequestMapping(value = "/folder/delete")
    @ResponseBody
    @BussinessLog(value = "删除个人文件夹")
    public Object deletefolder(@RequestParam Long folderId) {

        this.panFolderService.deleteFolder(folderId);

        return R.ok();
    }

    /**
     * 修改个人文件夹
     */
    @RequestMapping(value = "/folder/update")
    @ResponseBody
    @BussinessLog(value = "修改个人文件夹")
    public Object update(PanFolder folder) {
        if (CommonUtil.isOneEmpty(folder)) {
            throw new BizException(BizExceptionEnum.REQUEST_NULL);
        }
        PanFolder old = this.panFolderService.selectById(folder.getId());
        old.setName(folder.getName());
        old.setWeight(folder.getWeight());
        old.updateById();
        return R.ok();
    }

    /**
     * 转移个人文件夹
     */
    @RequestMapping(value = "/file/move")
    @ResponseBody
    @BussinessLog(value = "转移个人文件夹")
    public Object mobile(@RequestParam String fileIds,@RequestParam Long folderId) {
        if(fileIds != null){
            Long[] panFileIds = ArrayUtil.stringformatToArray(fileIds, ArrayUtil.COMMA);
            this.panFileService.moveToFolder(panFileIds, folderId);
        }
        return R.ok();
    }
	
}
